<html>
    <head>
        <title>带有缓存的 IServiceProvider</title>
    </head>
    <body>
        <script>
            /*
                        十七、带有缓存的ServiceProvider 
                                   ABP提供了两个特殊服务来优化来自IServiceProvider的解析服务。
                                   ICachedServiceProvider和ITransientCachedServiceProvider都继承自IServiceProvider接口，
                                   并在内部缓存已解析的服务，因此即使你多次解析服务，你也可以获得相同的服务实例。

                                   主要区别在于ICachedServiceProvider本身注册为作用域，而ITransientCachedServiceProvider注册为依赖注入系统的瞬态。

                                   以下示例注入ICachedServiceProvider服务，并在DoSomethingAsync方法中解析服务：

                                            public class MyService : ITransientDependency
                                            {
                                                private readonly ICachedServiceProvider _serviceProvider;


                                                public MyService(ICachedServiceProvider serviceProvider)
                                                {
                                                    _serviceProvider = serviceProvider;// 注入带有缓存的服务提供者服务
                                                }

                                                public async Task DoSomethingAsync()
                                                {
                                                    // 使用带有缓存的服务提供者来解析服务
                                                    var taxCalculator = _serviceProvider.GetRequiredService<ITaxCalculator>();
                                                    
                                                }
                                            } 
                                                
                                    使用这样的用法，你不需要释放创建的服务作用域范围和释放已解析的服务（如上面的发布/处置服务部分所解释的）。
                                    因为一旦释放了MyService实例的服务范围，从ICachedServiceProvider解析的所有服务都将被释放。
                                    此外，你不需要关心内存泄漏（因为如果我们调用DoSomethingAsync太多次，会创建太多的ITaxCalculator实例），因为只创建了一个ITaxCalculator实例，并且它被重用。

                                    由于ICachedServiceProvider和ITransientCachedServiceProvider扩展了标准的IServiceProvider接口，
                                    你可以在它们身上使用IServiceProvider接口的所有“扩展方法”。
                                    此外，它们还提供了一些其他方法来为未找到的服务提供默认值或工厂方法（即未注册到依赖注入系统）。
                                    请注意，默认值（或从你的工厂方法返回的值）也被缓存并重用。

                                    使用ICachedServiceProvider（而不是ITransientCachedServiceProvider），除非你需要每次使用创建服务缓存。
                                    ITransientCachedServiceProvider保证创建的服务实例不与任何其他服务共享，即使它们在同一个服务范围内。
                                    从ICachedServiceProvider解析的服务与同一服务范围内的其他服务共享（例如在同一个HTTP请求中），因此可以认为它更优化。
                    */
        </script>
    </body>
</html>